<template>
  <div>
    <div class="jsoneditor-vue"></div>
  </div>
</template>

<script>
import 'jsoneditor/dist/jsoneditor.css'
import JsonEditor from 'jsoneditor'
export default {
  name: 'VueJsonEditor',
  components: {
    JsonEditor
  },
  props: {
    value: [String, Number, Object, Array],
    mode: {
      type: String,
      default: 'tree'
    },
    modes: {
      type: Array,
      default: function() {
        return ['tree', 'code', 'form', 'view'];
      }
    }
  },
  watch: {
    value: {
      immediate: true,
      async handler(val) {
        if (!this.internalChange) {
          await this.setEditor(val);
          this.expandAll();
        }
      },
      deep: true
    }
  },
  data() {
    return {
      editor: null,
      error: false,
      json: this.value,
      internalChange: false,
      expandedModes: ['tree', 'view', 'form']
    };
  },
  mounted() {
    let self = this;
    let options = {
      mode: this.mode,
      modes: this.modes,
      onChange() {
        try {
          let json = self.editor.get();
          self.json = json;
          self.$emit('jsonChange', json);
          self.internalChange = true;
          self.$emit('input', json);
          self.$nextTick(function() {
            self.internalChange = false;
          });
        } catch(e) {
          self.$emit('hasError', e);
        }
      },
      onModeChange() {
        self.expandAll();
      }
    };
    this.editor = new JsonEditor(
      this.$el.querySelector('.jsoneditor-vue'),
      options,
      this.json
    );
  },
  methods: {
    expandAll() {
      if (this.expandedOnStart && this.expandedModes.includes(this.editor.getMode())) {
        this.editor.expandAll();
      }
    },
    async setEditor(value) {
      if (this.editor) {
        this.editor.set(value);
      }
    }
  }
}
</script>

<style scoped>
.jsoneditor-vue {
  height: calc(100vh - 218px);
  overflow-x: hidden;
  overflow-y: auto;
}
</style>